package breakout2014;

import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import levelEditor.LevelEditor;
import test.lineSegmentIntersectionTest.LineSegmentIntersection_UnitTest;
import java.util.logging.*;
import myLogger.MyLoggerSetup;


public class BreakoutMain extends SimpleApplication implements ActionListener, AnalogListener {
    private static final Logger logger = Logger.getLogger(BreakoutMain.class.getName());
    private long bulletCooldown;
    private Spatial racket, bullet, border1, border2, border3, brick, out, background;
    private Node bulletNode;
    private LevelEditor editor;
    boolean gameRunning = true;
    
    boolean isLevelEditor = true;
    
    
    public static void main(String[] args) {

        // Setup my logging settings and format
        MyLoggerSetup myLog = new MyLoggerSetup();
        
        if (true == false) {
            LineSegmentIntersection_UnitTest test = new LineSegmentIntersection_UnitTest();
        }
        else {
            BreakoutMain app = new BreakoutMain();
            // suppress starting resolution window
            app.setShowSettings(false);
            app.start();
        }
    }

    @Override
    public void simpleInitApp() {
//        setup camera for 2D games
        cam.setParallelProjection(true);
        cam.setLocation(new Vector3f(0,0,0.5f));
        getFlyByCamera().setEnabled(false);
        
//      turn off stats (you can leave it on, if you want)
        setDisplayStatView(false);
        setDisplayFps(true);
        
        
        if(isLevelEditor){
            editor = new LevelEditor(this);
        }
        else{
            
        
        
        
        
        
//        setup input handling
        inputManager.addMapping("mousePick", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        inputManager.addListener(this, "mousePick");
        inputManager.setCursorVisible(false);
        
        inputManager.addMapping("left", new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("right", new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addListener(this, "left");
        inputManager.addListener(this, "right");       
       

        
        
        // ######## BACKGROUND
        background = getSpatialTest("background1");
        background.setLocalTranslation(settings.getWidth()/2, settings.getHeight()/2, 0);
        float factorBackY = settings.getHeight() / ((BoundingBox)background.getWorldBound()).getYExtent();
        float factorBackX = settings.getWidth() / ((BoundingBox)background.getWorldBound()).getXExtent();
        background.scale(factorBackX/2,factorBackY/2,0);
        guiNode.attachChild(background);
        
        
        // ######## RACKET
        racket = getSpatial("racket");
        racket.setUserData("alive",true);       
        racket.scale(settings.getWidth()/2,1,0);
        racket.move(settings.getWidth()/2, 30, 0);
        racket.addControl(new RacketControl(settings.getWidth(), settings.getHeight(), inputManager));
        guiNode.attachChild(racket);
        
        // ######## BULLET
        Node bullets = new Node("bullets");
        guiNode.attachChild(bullets);
        bullet = getSpatial("bullet");
        bullet.setUserData("status", "StickOnRacket");
        bullet.setUserData("radius", ((BoundingBox)bullet.getWorldBound()).getYExtent());
        bullet.addControl(new BulletControl(guiNode, settings.getWidth(), settings.getHeight()));
        bullets.attachChild(bullet);
        
        // ######## OUT
        out = getSpatial("out");
        out.setLocalTranslation(settings.getWidth()/2, 0, 0);
        out.scale(20,1,0);
        guiNode.attachChild(out);
        
        // ######## BORDERS
        Node borders = new Node("borders");
        guiNode.attachChild(borders);
        //      setup up-borders
        border1 = getSpatial("border");
        border1.setLocalTranslation(settings.getWidth()/2, settings.getHeight()-20, 0);
        float factor1 = settings.getWidth() / ((BoundingBox)border1.getWorldBound()).getXExtent();
        border1.scale(factor1/2,0.1f,0);
        borders.attachChild(border1);
        //      setup left-borders
        border2 = getSpatial("border");
        border2.setLocalTranslation(20, settings.getHeight()/2, 0);
        float factor2 = settings.getHeight() / ((BoundingBox)border2.getWorldBound()).getYExtent();
        border2.rotate(0,0,FastMath.PI/2);
        border2.scale(factor2/2,0.1f,0);
        borders.attachChild(border2);
        //      setup right-borders
        border3 = getSpatial("border");
        border3.setLocalTranslation(settings.getWidth()-25, settings.getHeight()/2, 0);
        float factor3 = settings.getHeight() / ((BoundingBox)border3.getWorldBound()).getYExtent();
        border3.rotate(0,0,FastMath.PI/2);
        border3.scale(factor2/2,0.1f,0);
        borders.attachChild(border3);
      
        // ######## BRICKS
        Node bricks = new Node("bricks");
        guiNode.attachChild(bricks);
        // simple brick
        Vector3f pos = new Vector3f(0,0,0);
        int maxBricksPerLine = 1;
        int maxLines = 1;
        for(int iy=1; iy<=maxLines;iy++){
            for(int ix=1; ix<=maxBricksPerLine;ix++){
                pos.x=ix*settings.getWidth()/(maxBricksPerLine+1);
                pos.y=(iy*settings.getHeight()/2/(maxLines+1))+settings.getHeight()/3;
                addBrickMultiHit(bricks, pos);
            }
        }
        }
    }

    public void addBrick(Node bricks, Vector3f pos) {
        Spatial brick = getSpatial("brick");
        brick.setLocalTranslation(pos);
        brick.scale(0.46f,3,0);
        brick.setUserData("hit",false);
        brick.addControl(new BrickControl());
        bricks.attachChild(brick);
    
    }
    public void addBrickMultiHit(Node bricks, Vector3f pos) {
        Spatial brickMultiHit = getSpatial("brickMultiHit");
        brickMultiHit.setLocalTranslation(pos);
        brickMultiHit.scale(0.46f,3,0);
        brickMultiHit.setUserData("hit",false);
        brickMultiHit.addControl(new BrickMultiHitControl());
        bricks.attachChild(brickMultiHit);
    
    
    }
    
    @Override
    public void simpleUpdate(float tpf) {
        if(isLevelEditor){
            editor.screenUpdate();
        }
        else{
        //inputManager.setCursorVisible(false);
            // Check winning condition
            Node bricks = (Node)guiNode.getChild("bricks");
            if((bricks.getQuantity()==0)&&(gameRunning)){
                BitmapFont myFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
                BitmapText helloText = new BitmapText(myFont, false);
                helloText.setSize(100);
                helloText.setText("YOU WIN");
                helloText.setColor(ColorRGBA.Blue);
                float textOffsetX = helloText.getLineWidth()/2;
                float textOffsetY = helloText.getLineHeight()/2;
                helloText.setLocalTranslation(settings.getWidth()/2-textOffsetX,settings.getHeight()/2+textOffsetY,0);
                guiNode.attachChild(helloText); 
                gameRunning=false;
                Node bullets = (Node)guiNode.getChild("bullets");
                bullets.detachAllChildren();
            }
            // Check losing condition
            Node bullets = (Node)guiNode.getChild("bullets");
            if ((bullets.getQuantity()==0)&&(gameRunning)){
                BitmapFont myFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
                BitmapText helloText = new BitmapText(myFont, false);
                helloText.setSize(100);
                helloText.setText("GAME OVER");
                helloText.setColor(ColorRGBA.Blue);
                float textOffsetX = helloText.getLineWidth()/2;
                float textOffsetY = helloText.getLineHeight()/2;
                helloText.setLocalTranslation(settings.getWidth()/2-textOffsetX, settings.getHeight()/2+textOffsetY,0);
                guiNode.attachChild(helloText);    
                gameRunning=false;
            }
        }
    }

    @Override
    public void simpleRender(RenderManager rm) {}

    public void onAction(String name, boolean isPressed, float tpf) {
        if ((Boolean) racket.getUserData("alive")) {
            if (name.equals("left")) {
                racket.getControl(RacketControl.class).left = isPressed;
            } else if (name.equals("right")) {
                racket.getControl(RacketControl.class).right = isPressed;
            }
        }
    }

    public void onAnalog(String name, float value, float tpf) {
        if ((Boolean) racket.getUserData("alive")) {
            if (name.equals("mousePick")) {
               bullet.setUserData("status", "InTheAir"); 
               
            
               
  
                
                
                
                //shoot Bullet
                //if (System.currentTimeMillis() - bulletCooldown > 1000f) {
               
                    
                    
                    
                    //bulletCooldown = System.currentTimeMillis();
                    //Vector3f aim = getAimDirection();
                    //Spatial bullet = getSpatial("Bullet");
                    //Vector3f finalOffset = aim;
                    //Vector3f trans = player.getLocalTranslation().add(finalOffset);
                    //bullet.setLocalTranslation(trans);
                    //bullet.addControl(new BulletControl(aim, settings.getWidth(), settings.getHeight()));
                    //bulletNode.attachChild(bullet);
                    
                //}
            }
        }
    }
    
    private Vector3f getAimDirection() {
        Vector2f mouse = inputManager.getCursorPosition();
        Vector3f playerPos = racket.getLocalTranslation();
        Vector3f dif = new Vector3f(mouse.x-playerPos.x,mouse.y-playerPos.y,0);
        return dif.normalizeLocal();
    }
    
    public static float getAngleFromVector(Vector3f vec) {
        Vector2f vec2 = new Vector2f(vec.x,vec.y);
        return vec2.getAngle();
    }
    
    public static Vector3f getVectorFromAngle(float angle) {
        return new Vector3f(FastMath.cos(angle),FastMath.sin(angle),0);
    }
    
    private Spatial getSpatial(String name) {
        Node node = new Node(name);
//        load picture
        Picture pic = new Picture(name);
        Texture2D tex = (Texture2D) assetManager.loadTexture("Textures/"+name+".png");
        pic.setTexture(assetManager,tex,true);
        
//        adjust picture
        float width = tex.getImage().getWidth();
        float height = tex.getImage().getHeight();
        pic.setWidth(width);
        pic.setHeight(height);
        pic.move(-width/2f,-height/2f,0);
        
//        add a material to the picture
        Material picMat = new Material(assetManager, "Common/MatDefs/Gui/Gui.j3md");
        picMat.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);
        node.setMaterial(new Material());
        
//        set the radius of the spatial
//        (using width only as a simple approximation)
        node.setUserData("radius", width/2);
        
//        attach the picture to the node and return it
        node.attachChild(pic);
        return node;
    }

    
    private Spatial getSpatialTest(String name) {
        Node node = new Node(name);
//        load picture
        Picture pic = new Picture(name);
        Texture2D tex = (Texture2D) assetManager.loadTexture("Textures/"+name+".jpg");
        pic.setTexture(assetManager,tex,true);
        
//        adjust picture
        float width = tex.getImage().getWidth();
        float height = tex.getImage().getHeight();
        pic.setWidth(width);
        pic.setHeight(height);
        pic.move(-width/2f,-height/2f,0);
        
//        add a material to the picture
        Material picMat = new Material(assetManager, "Common/MatDefs/Gui/Gui.j3md");
        picMat.getAdditionalRenderState().setBlendMode(BlendMode.AlphaAdditive);
        node.setMaterial(new Material());
        
//        set the radius of the spatial
//        (using width only as a simple approximation)
        node.setUserData("radius", width/2);
        
//        attach the picture to the node and return it
        node.attachChild(pic);
        return node;
    }
    
    
    public AppSettings getSettings() {return settings;}
}


 